#include "LServer.h"
#include <assert.h>

#include <stdio.h>

typedef struct socketslist
{
	int num;
	SOCKET list[LSERVER_MAX_SOCKETS];
}LSOCKET_LIST;

typedef struct lprameter
{
	LSOCKET_LIST* package;
	LServer* server;
}LPRAMETER;

DWORD WINAPI LSOCKET_THREAD(LPVOID parameter)
{
	LPRAMETER* l = (LPRAMETER*)parameter;
	char buffer[LSERVER_BUFFER_LEN+1] = {0};

	while(l->server->m_run)
	{
		Sleep(10);
		for(int i = 0 ; i < l->package->num;i++)
		{
			SOCKET sock = l->package->list[i];

			if(sock == INVALID_SOCKET){continue;}

			int ret = recv(sock,buffer,LSERVER_BUFFER_LEN,0);

			if(ret == SOCKET_ERROR)	{continue;}

			if(ret == 0)
			{
				closesocket(l->package->list[i]);
				l->package->list[i] = INVALID_SOCKET;
				continue;
			}

			printf("recv:%d , get socket num:%d , index:%d\n",ret ,l->package->num,i );
			buffer[ret] = 0;
			sockaddr_in info;
			int len = sizeof(info);
			getsockname(sock,(sockaddr*)&info,&len);
			printf("IP:%s data:%s\n",inet_ntoa(info.sin_addr),buffer);
		}
	}

	for(int i = 0 ; i < l->package->num ; i++)
	{
		if(l->package->list[i] != INVALID_SOCKET)
		{
			closesocket(l->package->list[i]);
		}	
	}

	delete l->package;
	delete l;
	return 0;
}

void InitThreadNeedPrameter(LSOCKET_LIST** list,LPRAMETER** l,LServer* server)
{
	(*list) = new LSOCKET_LIST;
	memset((*list),0,sizeof(LSOCKET_LIST));
	(*l) = new LPRAMETER;
	(*l)->package = (*list);
	(*l)->server = server;
	HANDLE h  = CreateThread(0,0,LSOCKET_THREAD,(*l),0,0);
	CloseHandle(h);
}

LServer::LServer():m_run(false)
{

}

LServer::~LServer()
{
	m_run = false;
}	

void LServer::run()
{
	if(m_run){return;}
	m_run = true;

	int ret = m_winsock.Startup();
	assert( 0 == ret);
	if( 0 != ret )
	{
		printf("WSAStartup failed: %d\n",GetLastError());
		return;
	}

	SOCKET listenSock = m_winsock.TCPSocket();
	assert(listenSock != INVALID_SOCKET);
	if( listenSock == INVALID_SOCKET )
	{
		printf("listenSock failed: %d\n",GetLastError());
		return;
	}

	sockaddr_in info;
	m_winsock.SetSockAddrInfo(&info,LSERVER_HOST,LSERVER_PORT);

	ret = bind(listenSock,(sockaddr*)&info,sizeof(info));

	assert(ret != SOCKET_ERROR);
	if(ret == SOCKET_ERROR)
	{
		printf("bind failed: %d\n",GetLastError());
		goto run_end;
	}

	ret = listen(listenSock,SOMAXCONN);
	assert(ret != SOCKET_ERROR);
	if(ret == SOCKET_ERROR)
	{
		printf("listen failed: %d\n",GetLastError());
		goto run_end;
	}

	LSOCKET_LIST* list = NULL;
	LPRAMETER* l = NULL;
	InitThreadNeedPrameter(&list,&l,this);


	while(m_run)
	{
		SOCKET sock = accept(listenSock,0,0);

		if(sock == INVALID_SOCKET)
		{
			printf("accept socket failed: %d\n",GetLastError());
			continue;
		}

		u_long p = 1;
		if(SOCKET_ERROR == ioctlsocket(sock,FIONBIO,&p))
		{
			printf("ioctlsocket socket failed: %d\n",GetLastError());
			closesocket(sock);
			continue;
		}
		
		//list is full,new one
		if(list->num == LSERVER_MAX_SOCKETS)
		{
			InitThreadNeedPrameter(&list,&l,this);
		}

		list->list[list->num] = sock;
		list->num += 1;
	}

	if(list->num == 0)
	{
		delete list;
		delete l;
	}

run_end:
	closesocket(listenSock);
}

void LServer::stop()
{
	m_run = false;
}